using System;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using System.Xml.Xsl;
using System.Web;
using System.Data;
using System.Text;

namespace GlobalLib
{
    public class Xslt
    {
        public class Parameter
        {
            public Parameter(string name, object value)
            {
                this._name = name;
                this._value = value.ToString();
            }

            private string _name = "";
            private string _value = "";

            public string Name
            {
                get { return _name; }
            }

            public string Value
            {
                get { return _value; }
            }
        }

        public static string TransByWebPath(string web_path_xml, string path_xsl)
        {
            return TransByWebPath(web_path_xml, path_xsl, null);
        }

        public static string TransByWebPath(string web_path_xml, string path_xsl, Parameter[] lst)
        {
            XPathDocument doc = new XPathDocument(web_path_xml);

            string m_path_xsl = HttpContext.Current.Server.MapPath(path_xsl);
            XslCompiledTransform xslt = BuildXsltObj(m_path_xsl);

            StringWriter sw = new StringWriter();
            if (lst != null && lst.Length > 0)
            {
                XsltArgumentList list = new XsltArgumentList();
                foreach (Parameter obj in lst)
                {
                    list.AddParam(obj.Name, "", obj.Value);
                }
                xslt.Transform(doc, list, sw);
            }
            else
            {
                xslt.Transform(doc, null, sw);
            }

            return sw.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
        }

        public static string TransByPath(string path_xml, string path_xsl)
        {
            return TransByPath(path_xml, path_xsl, null);
        }

        public static string TransByPath(string path_xml, string path_xsl, Parameter[] lst)
        {
            string m_path_xml = HttpContext.Current.Server.MapPath(path_xml);
            XPathDocument doc = new XPathDocument(m_path_xml);

            string m_path_xsl = HttpContext.Current.Server.MapPath(path_xsl);
            XslCompiledTransform xslt = BuildXsltObj(m_path_xsl);

            StringWriter sw = new StringWriter();
            if (lst != null && lst.Length > 0)
            {
                XsltArgumentList list = new XsltArgumentList();
                foreach (Parameter obj in lst)
                {
                    list.AddParam(obj.Name, "", obj.Value);
                }
                xslt.Transform(doc, list, sw);
            }
            else
            {
                xslt.Transform(doc, null, sw);
            }

            return sw.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
        }

        public static string TransByData(string data_xml, string path_xsl)
        {
            return TransByData(data_xml, path_xsl, null);
        }

        public static string TransByData(string data_xml, string path_xsl, Parameter[] lst)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(data_xml);
            string m_path_xsl = HttpContext.Current.Server.MapPath(path_xsl);
            XslCompiledTransform xslt = BuildXsltObj(m_path_xsl);

            StringWriter sw = new StringWriter();
            if (lst != null && lst.Length > 0)
            {
                XsltArgumentList list = new XsltArgumentList();
                foreach (Parameter obj in lst)
                {
                    list.AddParam(obj.Name, "", obj.Value);
                }
                xslt.Transform(doc, list, sw);
            }
            else
            {
                xslt.Transform(doc, null, sw);
            }

            return sw.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
        }

        public static string TransByPathXmlDataXsl(string xml, string xsl, params Parameter[] xstyleParam)
        {
            string m_path_xml = HttpContext.Current.Server.MapPath(xml);
            XPathDocument doc = new XPathDocument(m_path_xml);

            XslCompiledTransform xslt = BuildXsltObjByData(xsl);

            StringWriter sw = new StringWriter();
            if (xstyleParam.Length > 0)
            {
                XsltArgumentList list = new XsltArgumentList();
                foreach (Parameter obj in xstyleParam)
                {
                    list.AddParam(obj.Name, "", obj.Value);
                }
                xslt.Transform(doc, list, sw);
            }
            else
            {
                xslt.Transform(doc, null, sw);
            }

            return sw.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
        }

        public static string TransByDataXmlDataXsl(string xml, string xsl, params Parameter[] xstyleParam)
        {
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            XslCompiledTransform xslt = BuildXsltObjByData(xsl);

            StringWriter sw = new StringWriter();
            if (xstyleParam.Length > 0)
            {
                XsltArgumentList list = new XsltArgumentList();
                foreach (Parameter obj in xstyleParam)
                {
                    list.AddParam(obj.Name, "", obj.Value);
                }
                xslt.Transform(doc, list, sw);
            }
            else
            {
                xslt.Transform(doc, null, sw);
            }

            return sw.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
        }

        public static string TransByWebXmlDataXsl(string xml, string xsl, params Parameter[] xstyleParam)
        {
            XPathDocument doc = new XPathDocument(xml);
            XslCompiledTransform xslt = BuildXsltObjByData(xsl);

            StringWriter sw = new StringWriter();
            if (xstyleParam.Length > 0)
            {
                XsltArgumentList list = new XsltArgumentList();
                foreach (Parameter obj in xstyleParam)
                {
                    list.AddParam(obj.Name, "", obj.Value);
                }
                xslt.Transform(doc, list, sw);
            }
            else
            {
                xslt.Transform(doc, null, sw);
            }

            return sw.ToString().Replace("<?xml version=\"1.0\" encoding=\"utf-16\"?>", "");
        }

        public static string XmlHeader_Root(string data_xml)
        {
            return @"
				<root>" + data_xml + @"</root>
			";
        }

        public static string XmlHeader_UTF8(string data_xml)
        {
            return @"
				<?xml version='1.0' encoding='utf-8' ?>
				<root>" + data_xml + @"</root>
			";
        }

        public static string XmlHeader_GB(string data_xml)
        {
            return @"
				<?xml version='1.0' encoding='gb2312' ?>
				<root>" + data_xml + @"</root>
			";
        }

        public static string DataTable2Xml(DataTable data)
        {
            StringBuilder sb = new StringBuilder("<?xml version='1.0' encoding='utf-8' ?><root>");
            foreach (DataRow row in data.Rows)
            {
                sb.Append("<row>");
                foreach (DataColumn column in data.Columns)
                {
                    sb.AppendFormat("<{0}><![CDATA[{1}]]></{0}>", column.ColumnName, row[column]);
                }

                sb.Append("</row>");
            }
            sb.Append("</root>");
            return sb.ToString();
        }

        public static string AppendPagedInfo(string dataXml, int current, int pageSize, int records)
        {
            if (current == 0 || pageSize <= 0)
                return dataXml;

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(dataXml);
            var root = doc.SelectSingleNode("/*");
            int pageCount = records % pageSize > 0 ? records / pageSize + 1 : records / pageSize;

            XmlNode paged = doc.CreateElement("paged");
            for (int i = 0; i < pageCount; i++)
            {
                int tmp = i + 1;
                XmlNode node = doc.CreateElement("page");
                XmlAttribute num = doc.CreateAttribute("num");
                num.Value = tmp.ToString();
                node.Attributes.Append(num);
                if (tmp == current)
                {
                    XmlAttribute currentAttr = doc.CreateAttribute("is_current");
                    currentAttr.Value = "1";
                    node.Attributes.Append(currentAttr);
                }

                paged.AppendChild(node);
            }

            root.AppendChild(paged);
            return doc.OuterXml;
        }

        private static XslCompiledTransform BuildXsltObjByData(string xslData)
        {
            StringReader sr = new StringReader(xslData);
            XmlReader reader = new System.Xml.XmlTextReader(sr);

            XslCompiledTransform xslt = new XslCompiledTransform();
            XsltSettings settings = XsltSettings.TrustedXslt;
            settings.EnableDocumentFunction = true;
            xslt.Load(reader,
                settings,
                new XmlUrlResolver());
            return xslt;

        }

        private static XslCompiledTransform BuildXsltObj(string path)
        {
            XslCompiledTransform xslt = new XslCompiledTransform();
            XsltSettings settings = XsltSettings.TrustedXslt;
            settings.EnableDocumentFunction = true;
            xslt.Load(path, settings, new XmlUrlResolver());
            return xslt;
        }
    }
}
